﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace HttpConsole
{
    public partial class Form1 : Form
    {
        private const int port = 80;
        // default url
        private string urlPath = "http://205.196.123.192/665wob12nhag/y4nwlfqzjwc/Planetarian+OST.rar";
        private string uriPath = "";
        private string hostName = "";
        Socket sock;
        Thread thread;
        string recivedBuffer = "";
        bool stopRecive = false;

        /* Manage update */

        System.Windows.Forms.Timer updateTimer;
        bool updateReciverText = false;

        /* HTTP prototypes */
        const string getPrototype = "GET /@URI@ HTTP/1.1\r\nHost: @HOST@" +
            "\r\nConnection: Keep-Alive\r\n\r\n";

        public Form1()
        {
            InitializeComponent();
            this.url.Text = urlPath;
            // setup UI
            this.getMethod.CheckedChanged += new EventHandler(getMethod_CheckedChanged);
            this.getMethod.Checked = true;
            // update request header
            this.request.Text = HttpGet;
            // init and start update timer
            this.updateTimer = new System.Windows.Forms.Timer();
            this.updateTimer.Interval = 500;
            this.updateTimer.Tick += new EventHandler(updateTimer_Tick);
            this.updateTimer.Start();
            // get data from socket
            this.thread = new Thread(new ThreadStart(this.GetDataFromSocket));
            thread.Start();
        }

        void getMethod_CheckedChanged(object sender, EventArgs e)
        {
            if (getMethod.Checked)
            {
                this.request.Text = HttpGet;
            }
        }

        public string HttpGet
        {
            get
            {

               UpdateHeader();
               string header = "";
               header = getPrototype.Replace("@URI@", this.uriPath);
               header = header.Replace("@HOST@", this.hostName);
               return header;
            }
        }

        private void UpdateHeader()
        {
            string parseUrl = this.urlPath.Replace("http://", "");
            int index = parseUrl.IndexOf('/');
            string[] parseUrls = parseUrl.Split(new char[] {'/'}, 2);

            this.hostName = parseUrls[0];
            this.uriPath = parseUrls[1];
        }

        private void Connect()
        {
            if (sock!= null && sock.Connected)
            {
                return;
            }
            string[] hostParses = this.hostName.Split(new char[] {'.'});
            bool isIP = false;
            int outInt;
            foreach (var item in hostParses)
            {
                if (int.TryParse(item, out outInt) == true)
                {
                    isIP = true;
                    break;
                }
            }
            IPHostEntry ipAddress;
            
            IPEndPoint ip;
            if (isIP == false)
            {
                ipAddress = Dns.GetHostEntry(this.hostName);
                ip = new IPEndPoint(ipAddress.AddressList[0], port);
            }
            else
            {
                ip = new IPEndPoint(IPAddress.Parse(this.hostName), port);
            }
           
            sock = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                sock.Connect(ip);
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.ToString(), "Connect fail", MessageBoxButtons.OK);
            }
        }

        void updateTimer_Tick(object sender, EventArgs e)
        {
            if (this.updateReciverText == true)
            {
                this.updateReciverText = false;
                this.respond.Text = this.recivedBuffer;
            }
        }

        private void GetDataFromSocket()
        {
            
            byte[] buffer = new byte[1024];
            do
            {
                try
                {
                    if (this.sock != null && this.sock.Available > 0)
                    {
                        int n = this.sock.Receive(buffer);
                        recivedBuffer += Encoding.UTF8.GetString(buffer, 0, n);
                        this.updateReciverText = true;
                    }
                }
                catch (Exception exc)
                {
                    Console.WriteLine(exc.ToString());
                }
                Thread.Sleep(100);
            }
            while (this.stopRecive == false);
        }

        private void get_Click(object sender, EventArgs e)
        {
            // clear buffer
            recivedBuffer = "";
            this.respond.Clear();
            string s = this.request.Text;
            byte[] buffer = Encoding.UTF8.GetBytes(s);
            try
            {
                this.Connect();
                this.sock.Send(buffer);
                this.sock.Disconnect(false);
            }
            catch(Exception exc)
            {
                Console.WriteLine(exc.ToString());
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.stopRecive = true;
        }

        private void url_TextChanged(object sender, EventArgs e)
        {
            this.urlPath = url.Text;
            this.request.Text = HttpGet;
        }
    }
}
